package cl.uchile.sketchpad.web.controllers;

import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import cl.uchile.sketchpad.persistance.model.Activity;
import cl.uchile.sketchpad.persistance.model.SubjectVersion;
import cl.uchile.sketchpad.persistance.model.SubjectVersionRegistration;
import cl.uchile.sketchpad.persistance.model.User;
import cl.uchile.sketchpad.services.ActivityService;
import cl.uchile.sketchpad.services.SubjectService;
import cl.uchile.sketchpad.services.SubjectVersionRegistrationService;
import cl.uchile.sketchpad.services.SubjectVersionService;
import cl.uchile.sketchpad.services.UserService;
import cl.uchile.sketchpad.web.controllers.util.SktUtil;


@Controller
public class SubjectsController {
	
	private static final Logger LOG = LoggerFactory.getLogger(SubjectsController.class);

	@Autowired private UserService userService;
	@Autowired private SubjectService subjectService;
	@Autowired private SubjectVersionService subjectVersionService;
	@Autowired private SubjectVersionRegistrationService subjectVersionRegistrationService;
	@Autowired private ActivityService activityService;
	

	@Transactional
	@RequestMapping(value = "/subjectVersionSelection", method = { POST , GET })
	public String subjectVersionSelection(HttpServletRequest request, Model model) {
		
		User user = this.userService.getUser(request);
		if ( user == null || user.getId() == null )
			return "redirect:/";
		model.addAttribute("user", user);
		
		model.addAttribute("subjects", this.subjectService.getSubjects());
		
		List<SubjectVersion> subjectVersions = new ArrayList<SubjectVersion>(0);
		
		if ( SktUtil.isTeacherOrAdmin(user) )
			subjectVersions.addAll(this.subjectVersionService.getAll());
		else
			subjectVersions.addAll(user.getSubjectVersions());
		
		model.addAttribute("subjectVersions", subjectVersions);
		
		return "subjectVersionSelection";
	}
	
	@Transactional
	@RequestMapping(value = "/addSubjectVersion", method = { POST })
	public String addSubjectVersion(
			HttpServletRequest request,
			HttpServletResponse response,
			Model model,
			@RequestParam("subject_id") Integer subjectId,
			@RequestParam("version_name") String versionName)
	{
		User user = this.userService.getUser(request);
		if ( user == null || user.getId() == null )
			return "redirect:/";
		model.addAttribute("user", user);
		
		if ( !SktUtil.isTeacherOrAdmin(user) ) {

			String desc = "You don't have permission to create subjects";
			model.addAttribute("alert", "error");
			model.addAttribute("alertdesc", desc);
			try {
				response.sendError(403, desc);
			} catch (IOException e) {
				e.printStackTrace(System.err);
				LOG.error(e.getLocalizedMessage(), e);
			}
			
		} else {
			
			SubjectVersion subjectVersion = new SubjectVersion();
			try {
				if ( versionName == null || "".equals(versionName) )
					throw new IllegalArgumentException("Version name can't be null");
				
				subjectVersion.setName(versionName);
				subjectVersion.setSubject(this.subjectService.findById(subjectId));
				subjectVersion.setDate(new Date());
				subjectVersion.setUsers(new HashSet<User>());
				subjectVersion.getUsers().add(user);
				this.subjectVersionService.persist(subjectVersion);
				
				model.addAttribute("alert", "success");
			} catch ( Exception e ) {
				model.addAttribute("alert", "error");
				model.addAttribute("alertdesc", e.getLocalizedMessage());
				e.printStackTrace(System.err);
				LOG.error(e.getLocalizedMessage(), e);
			}
			
		}
		
		return this.subjectVersionSelection(request, model);
	}
	
	@Transactional
	@RequestMapping(value = "/registerSubjectVersionUsers/{subjectVersionId}", method = { GET , POST })
	public String registerSubjectVersionUsers(
			HttpServletRequest request,
			Model model,
			@RequestParam(value = "students_mails_json", required = false) String studentsMailsJson,
			@PathVariable Integer subjectVersionId
	) {
		User user = this.userService.getUser(request);
		if ( user == null || user.getId() == null || !"teacher".equals(user.getType()) )
			return "redirect:/";
		model.addAttribute("user", user);		
		
		SubjectVersion subjectVersion = this.subjectVersionService.findById(subjectVersionId);
		model.addAttribute("subjectVersion", subjectVersion);
		
		ArrayList<User> students = new ArrayList<User>(subjectVersion.getUsers());
		
		if ( !(studentsMailsJson == null || "".equals(studentsMailsJson)) ) {
			try {
				
				String[] mails = studentsMailsJson.split(",");
				List<String> mailsList = new ArrayList<String>(mails.length);
				
				for (String mail : mails) {
					if ( mail != null && !"".equals(mail) )
						mailsList.add(mail.trim());
				}
				
				this.subjectVersionRegistrationService.persistMailRegistrations(mailsList, subjectVersion);
				
				List<User> assignedUsers = this.subjectVersionRegistrationService.assignSubjectVersionUsers().get(subjectVersion);
				students.addAll(assignedUsers);
				
				model.addAttribute("alert", "success");
				
			} catch ( Exception e ) {
				e.printStackTrace(System.err);
				LOG.error(e.toString(), e);
			}
		}		

		List<SubjectVersionRegistration> queuedRegistrations = this.subjectVersionRegistrationService.getAll();
		for ( SubjectVersionRegistration qr : queuedRegistrations ) {
			if ( qr.getSubjectVersion().equals(subjectVersion) ) {
				User newUser = new User();
				newUser.setName(qr.getUserMail());
				newUser.setMail(qr.getUserMail());
				newUser.setUsername(qr.getUserMail());
				students.add(newUser);
			}
		}

		model.addAttribute("students", students);
		
		return "registerSubjectVersionUsers";
	}
	
	@Transactional
	@RequestMapping(value = "/activitySelection/{subjectVersionId}", method = { GET, POST })
	public String activitySelection(
			HttpServletRequest request,
			Model model,
			@PathVariable Integer subjectVersionId,
			@RequestParam(value = "alert", required = false) String alert,
			@RequestParam(value = "alertdesc", required = false) String alertdesc)
	{
		User user = this.userService.getUser(request);
		if ( user == null || user.getId() == null )
			return "redirect:/";
		model.addAttribute("user", user);
		
		SubjectVersion subjectVersion = subjectVersionService.findById(subjectVersionId);
		model.addAttribute("subjectVersion", subjectVersion);
		model.addAttribute("activities", new ArrayList<Activity>(subjectVersion.getActivities()));
		
		if ( alert != null && !"".equals(alert) ) {
			model.addAttribute("alert", alert);
			model.addAttribute("alertdesc", alertdesc);
		}
		
		return "activitySelection";
	}
	
	@Transactional
	@RequestMapping(value = "/addActivity", method = { POST })
	public String addActivity(
			HttpServletRequest request,
			Model model,
			@RequestParam("subject_version_id") Integer subjectVersionId,
			@RequestParam("name") String name)
	{
		User user = this.userService.getUser(request);
		if ( user == null || user.getId() == null )
			return "redirect:/";
		
		if ( !SktUtil.isTeacherOrAdmin(user) ) {
			String desc = "You don't have permission to create subjects";
			System.err.println(desc);
			LOG.error(desc);
			return this.activitySelection(request, model, subjectVersionId, "error", desc);			
		}
		
		if ( name == null || "".equals(name) )
			return this.activitySelection(request, model, subjectVersionId, "error", "The name of the activity can not be empty.");
				
		SubjectVersion subjectVersion = this.subjectVersionService.findById(subjectVersionId);
		
		Activity activity = new Activity();
		activity.setAuthor(user);
		activity.setDate(new Date());
		activity.setName(name);
		activity.setSubjectVersion(subjectVersion);
		this.activityService.persist(activity);
		
		return this.activitySelection(request, model, subjectVersionId, null, null);
	}
	
	
}
